package org.jhulk.tests;

import org.jhulk.sprites.Marine;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.XMLPackedSheet;
import org.newdawn.slick.tiled.TiledMap;

public class TiledMovement extends BasicGame {

    private TiledMap map;

    private Marine marine;

    private String mapName;

    private int click_x = 0;

    private int click_y = 0;
//
    private int marine_x = 42;

    private int marine_y = 42;

    private boolean ctrlPressed = false;

    private String[] msgs;

    private int clickedTileId;

    /** how long did we wait already until next update */
    private int updateCounter = 0;

    /** changing some tile of the map every UPDATE_TIME milliseconds */
    private static int UPDATE_TIME = 1000;

    /** we want to store the originalTileID before we set a new one */
    private int originalTileID = 0;

    public TiledMovement()
    {
        super("Moving about a Tiled Map test");
    }

    @Override
    public void init(GameContainer arg0)
        throws SlickException
    {
        map = new TiledMap("data/maps/testTileset.tmx");

        XMLPackedSheet sheet = new XMLPackedSheet("data/img/packedTest.png", "data/img/packedTest.png.xml");
        marine = new Marine(sheet.getSprite("marine_42.png"));

        // read some properties from map and layer
        mapName = map.getMapProperty("title", "Unknown map name");

        // store the original tile id of layer 0 at 1, 6
        originalTileID = map.getTileId(1, 6, 0);

    }

    @Override
    public void update(GameContainer container, int delta)
        throws SlickException
    {
        updateCounter += delta;
        if (updateCounter > UPDATE_TIME)
        {
            // swap the tile every second
            updateCounter -= UPDATE_TIME;

            int currentTileID = map.getTileId(1, 6, 0);
            if (currentTileID != originalTileID)
                map.setTileId(1, 6, 0, originalTileID);
            else
                map.setTileId(1, 6, 0, 10);
        }
    }

    @Override
    public void render(GameContainer container, Graphics g)
        throws SlickException
    {
        map.render(0, 0);

        marine.rotate(0.0f);
        marine.draw(marine_x, marine_y);

        //g.drawString("Click a tile to place the marine", 100, 385);

        g.drawString(mapName, 135, 50);
        g.drawString("Move up and down with arrow keys", 100, 400);
        g.drawString("Rotate marine with right and left arrows while holding ctrl", 100, 415);

    }


    public void mouseReleased(int button, int x, int y)
    {
        click_x = x;
        click_y = y;
        clickedTileId = determineTileIdFromXY(click_x, click_y);
        System.out.println("\n");
    }

    public int determineTileIdFromXY(int x, int y)
    {
        System.out.println("Determining tile ID at " + x + ", " + y);

        int retInt = 0;

        int tileX = getTileXfromPoint(x);

        int tileY = getTileYfromPoint(y);

        System.out.println("Tile X,Y: " + tileX + "," + tileY);

        if(tileX >= 0 && tileY >= 0)
        {
            retInt = map.getTileId(tileX, tileY, 0);
            System.out.println("Tile ID: " + retInt);
        }
        return retInt;
    }

    public int getTileXfromPoint(int pointX)
    {
        return Math.round(pointX/map.getTileHeight());
    }

    public int getTileYfromPoint(int pointY)
    {
        return Math.round(pointY/map.getTileWidth());
    }


    public void keyPressed(int key, char c)
    {
        if(key == Input.KEY_LCONTROL || key == Input.KEY_RCONTROL) ctrlPressed = true;

        if(ctrlPressed)
        {
            if(key == Input.KEY_LEFT) marine.turnLeft();

            if(key == Input.KEY_RIGHT) marine.turnRight();
        }
        else
        {
            if(key ==  Input.KEY_LEFT && canMoveX(marine_x, marine_y, -1))
            {
                if(key == Input.KEY_LEFT) marine_x -= marine.getMoveX();
            }

            if(key == Input.KEY_RIGHT && canMoveX(marine_x, marine_y, 1))
            {
                if(key == Input.KEY_RIGHT) marine_x += marine.getMoveX();
            }
        }

        if(key == Input.KEY_UP && canMoveY(marine_x, marine_y, -1))
        {
            if(key == Input.KEY_UP) marine_y -= marine.getMoveY();
        }

        if(key == Input.KEY_DOWN && canMoveY(marine_x, marine_y, 1))
        {
            if(key == Input.KEY_DOWN) marine_y += marine.getMoveY();
        }

        if(key == Input.KEY_SPACE) performCharAction();

        if(key == Input.KEY_ESCAPE) System.exit(0);

    }

    /**
     * Check the horizontal bounds
     * @param x
     * @param y
     * @return
     */
    public boolean canMoveX(int x, int y, int dir)
    {
        System.out.println("Enter: canMoveX");

        boolean canMove = false;

        do
        {
            //Find the tile coordinates of the next move
            int futureXPos = (dir > 0) ? (marine_x + marine.getMoveX()) : (marine_x - marine.getMoveX());

            System.out.println("marine_x: " + marine_x);
            System.out.println("-future X position would be: " + futureXPos);

            //Check if there is a valid tileID
            int futureTileId = determineTileIdFromXY(futureXPos, marine_y);

            if(futureTileId == 0)
            {
                System.out.println("Can't move there, no tile!");
                break;
            }

            //Check if the player can move to the tile or if something is blocking him
            String impassable = map.getTileProperty(futureTileId, "impassable", "");
            if(impassable != "")
            {
                System.out.println("Something is in the way!!");
                break;
            }

            canMove = true;
            break;

        } while(true);

        System.out.println("Exit: canMoveX\n");

        return canMove;
    }


    /**
     * Check the vertical bounds
     * @param x
     * @param y
     * @return
     */
    public boolean canMoveY(int x, int y, int dir)
    {
        System.out.println("Enter: canMoveY");

        boolean canMove = false;
        do
        {
            //Find the tile coordinates of the next move
            int futureYPos = (dir > 0) ? (marine_y + marine.getMoveY()) : (marine_y - marine.getMoveY());

            System.out.println("marine_y: " + marine_y);
            System.out.println("-future Y position would be: " + futureYPos);

            //Check if there is a valid tileID
            int futureTileId = determineTileIdFromXY(marine_x, futureYPos);

            if(futureTileId == 0)
            {
                System.out.println("Can't move there, no tile!");
                break;
            }

            //Check if the player can move to the tile or if something is blocking him
            String impassable = map.getTileProperty(futureTileId, "impassable", "");
            if(impassable != "")
            {
                System.out.println("Something is in the way!!");
                break;
            }

            canMove = true;
            break;

        } while(true);

        System.out.println("Exit: canMoveY\n");

        return canMove;
    }

    public void keyReleased(int key, char c)
    {
        if(key == Input.KEY_LCONTROL || key == Input.KEY_RCONTROL)
            ctrlPressed = false;
    }

    public void performCharAction()
    {
        // determine what is in "front" of the character
        float curRot = Math.abs(marine.getRotation()); //can only be 0,90,180,270
        System.out.println("Current rotation: " + curRot);
        int futYPos = marine_y;
        int futXPos = marine_x;
        int futureTileId = 0;


        do
        {
            //Facing north
            if(curRot == 0.0)
            {
                futYPos = marine_y - marine.getMoveY();
                futureTileId = determineTileIdFromXY(marine_x, futYPos);
                break;
            }



            if(curRot == 180.0)
            {
                futYPos = marine_y + marine.getMoveY();
                futureTileId = determineTileIdFromXY(marine_x, futYPos);
                break;
            }

            if(curRot == 90.0)
            {
                futXPos = marine_x - marine.getMoveX();
                futureTileId = determineTileIdFromXY(futXPos, marine_y);
                break;
            }

            if(curRot == 270.0)
            {
                futXPos = marine_x - marine.getMoveX();
                futureTileId = determineTileIdFromXY(futXPos, marine_y);
                break;
            }

            break;
        }while(true);

        if(futureTileId != 0)
        {
            String action = map.getTileProperty(futureTileId, "action", "");

            System.out.println("action: " + action);

            if(action.equals("") == false)
            {
                map.setTileId(
                        getTileXfromPoint(futXPos),
                        getTileYfromPoint(futYPos),
                        0,
                        Integer.parseInt(action));
            }
            else
            {
                System.out.println("Nothing to perform an action on!!\n");
            }
        }


    }

    public static void main(String[] args)
    {
        try {
            AppGameContainer app = new AppGameContainer(new TiledMovement());
            app.setDisplayMode(800, 600, false);
            app.start();
        } catch (SlickException e) {
            e.printStackTrace();
        }
    }
}
